/* ========================================
 *
 * Copyright YOUR COMPANY, THE YEAR
 * All Rights Reserved
 * UNPUBLISHED, LICENSED SOFTWARE.
 *
 * CONFIDENTIAL AND PROPRIETARY INFORMATION
 * WHICH IS THE PROPERTY OF your company.
 *
 * ========================================
*/

/* [] END OF FILE */
#include <stdlib.h>

/* Scheduler include files. */
#include "FreeRTOS.h"
#include "task.h"

/* Demo program include files. */
#include "project.h"
#include "main.h"
#include "attitude.h"
#include "hrss.h"

void CyBle_AsixWriteEventHandler(CYBLE_GATTS_WRITE_REQ_PARAM_T *eventParam)
{
    uint32 eventCode = 0u;
    CYBLE_GATT_ERR_CODE_T gattErr = CYBLE_GATT_ERR_NONE;
    CYBLE_HRS_CHAR_VALUE_T locCharIndex;

    locCharIndex.connHandle = eventParam->connHandle;
    locCharIndex.value = NULL;
    
    if(eventParam->handleValPair.attrHandle == CYBLE_CUSTOM_SERVICE_ORIGIN_DATA_CLIENT_CHARACTERISTIC_CONFIGURATION_DESC_HANDLE)
    {
        /* Heart Rate Measurement characteristic descriptor write request */
        if(CYBLE_IS_NOTIFICATION_ENABLED_IN_PTR(eventParam->handleValPair.value.val))
        {
            eventCode = (uint32)CYBLE_EVT_ASIX_NOTIFICATION_ENABLED;
        }
        else
        {
            eventCode = (uint32)CYBLE_EVT_ASIX_NOTIFICATION_DISABLED;
        }
        
        cyBle_eventHandlerFlag &= (uint8)~CYBLE_CALLBACK;
    }
    else if(eventParam->handleValPair.attrHandle == CYBLE_CUSTOM_SERVICE_CUSTOM_DATA_CLIENT_CHARACTERISTIC_CONFIGURATION_DESC_HANDLE)
    {
        /* Heart Rate Measurement characteristic descriptor write request */
        if(CYBLE_IS_NOTIFICATION_ENABLED_IN_PTR(eventParam->handleValPair.value.val))
        {
            eventCode = (uint32)CYBLE_EVT_ASIX_NOTIFICATION_ENABLED;
        }
        else
        {
            eventCode = (uint32)CYBLE_EVT_ASIX_NOTIFICATION_DISABLED;
        }
        
        cyBle_eventHandlerFlag &= (uint8)~CYBLE_CALLBACK;
    }
    
    if(0u != eventCode)
    {
        gattErr = CyBle_GattsWriteAttributeValue(&eventParam->handleValPair, 0u, 
                    &eventParam->connHandle, CYBLE_GATT_DB_PEER_INITIATED);
        
        if(CYBLE_GATT_ERR_NONE == gattErr)
        {
//            if(NULL != CyBle_HrsApplCallback)
//            {
//                CyBle_HrsApplCallback(eventCode, &locCharIndex);
//            }
//            else
//            {
//                CyBle_ApplCallback(CYBLE_EVT_GATTS_WRITE_REQ, eventParam);
//            }
        }
    }
    
    if((cyBle_eventHandlerFlag & CYBLE_CALLBACK) == 0u)
    {
        if(gattErr != CYBLE_GATT_ERR_NONE)
        {
            CYBLE_GATTS_ERR_PARAM_T err_param;
            
            err_param.opcode = (uint8) CYBLE_GATT_WRITE_REQ;
            err_param.attrHandle = eventParam->handleValPair.attrHandle;
            err_param.errorCode = gattErr;

            /* Send Error Response */
            (void)CyBle_GattsErrorRsp(eventParam->connHandle, &err_param);
        }
        else
        {
            (void)CyBle_GattsWriteRsp(eventParam->connHandle);
        }
    }
}

portTASK_FUNCTION( vBleProcessTask, pvParameters )
{
    TickType_t xLastFlashTime,delay = 20;
    CYBLE_API_RESULT_T apiResult;
    CYBLE_GATT_ERR_CODE_T res;
    CYBLE_GATT_HANDLE_VALUE_PAIR_T ntfReqParam;
    extern Attitude_Data attitude_atri;

	/* The parameters are not used. */
	( void ) pvParameters;



	/* We need to initialise xLastFlashTime prior to the first call to 
	vTaskDelayUntil(). */
	xLastFlashTime = xTaskGetTickCount();

	for(;;)
	{
		/* Delay for half the flash period then turn the LED on. */
		vTaskDelay( delay );
        
        if(attitude_atri.index != 0)
        {            
            /* Send Notification if it is enabled and connected */
            if(CYBLE_STATE_CONNECTED != CyBle_GetState())
            {
                apiResult = CYBLE_ERROR_INVALID_STATE;
            }
            else 
            {
                if(CYBLE_IS_NOTIFICATION_ENABLED(CYBLE_CUSTOM_SERVICE_ORIGIN_DATA_CLIENT_CHARACTERISTIC_CONFIGURATION_DESC_HANDLE))
                {
                    /* Fill all fields of write request structure ... */
                    ntfReqParam.attrHandle = CYBLE_CUSTOM_SERVICE_ORIGIN_DATA_CHAR_HANDLE; 
                    ntfReqParam.value.val = attitude_atri.ptr_data;
                    ntfReqParam.value.len = attitude_atri.index;
                    
                    /* Send notification to client using previously filled structure */
                    apiResult = CyBle_GattsNotification(cyBle_connHandle, &ntfReqParam);    
                    
                }
                else if(CYBLE_IS_NOTIFICATION_ENABLED(CYBLE_CUSTOM_SERVICE_CUSTOM_DATA_CLIENT_CHARACTERISTIC_CONFIGURATION_DESC_HANDLE))
                {
                    /* Fill all fields of write request structure ... */
                    ntfReqParam.attrHandle = CYBLE_CUSTOM_SERVICE_CUSTOM_DATA_CHAR_HANDLE; 
                    int16 tmp_data[7];
                    tmp_data[0] = attitude_atri.ned[0];
                    tmp_data[1] = attitude_atri.ned[1];
                    tmp_data[2] = attitude_atri.ned[2];
                    tmp_data[3] = attitude_atri.acc[0];
                    tmp_data[4] = attitude_atri.acc[1];
                    tmp_data[5] = attitude_atri.acc[2];
                    tmp_data[6] = 'i' << 8 | 'i';
                    
                    ntfReqParam.value.val = (uint8*)tmp_data;
                    ntfReqParam.value.len = 14;
                    
                    /* Send notification to client using previously filled structure */
                    apiResult = CyBle_GattsNotification(cyBle_connHandle, &ntfReqParam);    
                    
                }
                else
                {
                    apiResult = CYBLE_ERROR_NTF_DISABLED;
                }
            }
            attitude_atri.index = 0;
        }

		CyBle_ProcessEvents();
        

	}
} /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */


void vStartBleProcessTasks( UBaseType_t uxPriority )
{
	/* Create the three tasks. */
		/* Spawn the task. */
	xTaskCreate( vBleProcessTask, "BLEProcess", 400, NULL, uxPriority, ( TaskHandle_t * ) NULL );
}

portTASK_FUNCTION( vHrssProcessTask, pvParameters )
{
    TickType_t xLastFlashTime,delay = 500;

	/* The parameters are not used. */
	( void ) pvParameters;



	/* We need to initialise xLastFlashTime prior to the first call to 
	vTaskDelayUntil(). */
	xLastFlashTime = xTaskGetTickCount();

	for(;;)
	{
		/* Delay for half the flash period then turn the LED on. */
		vTaskDelay( delay );
        
	    SimulateHeartRate();
	}
} /*lint !e715 !e818 !e830 Function definition must be standard for task creation. */


void vStartHrssProcessTasks( UBaseType_t uxPriority )
{
	/* Create the three tasks. */
		/* Spawn the task. */
	xTaskCreate( vHrssProcessTask, "HrssProcess", 500, NULL, uxPriority, ( TaskHandle_t * ) NULL );
}